# -*- coding:utf-8 -*-

import os
import time
import unittest
from common import ReadConfig
from third import HTMLTestRunnerCN
from common.OperationExcel import OperationExcel

_DEFAULT_CASE_PATH = os.path.dirname(os.path.abspath(__file__)) + r'/../testCase/'
_TEMP_PATH = os.path.dirname(os.path.abspath(__file__)) + r"/../tmp/"

_NOW = time.strftime("%Y%m%d%H%M%S", time.localtime())
_REPORT_PATH = os.path.dirname(os.path.abspath(__file__)) + '/../report/'


class TestSuite:

    def __init__(self):
        self.excel = OperationExcel()
        self.cases = self.excel.get_all_case()

    @staticmethod
    def write_head(filename):
        """
        写测试套件的引用信息
        :param filename:
        :return:
        """
        handler = open(filename, 'w', encoding='utf-8')
        handler.write('# -*- coding:utf-8 -*-' + '\n')
        handler.write('import inspect' + '\n')
        handler.write('import unittest' + '\n')
        handler.write('from common.OperationJson import *' + '\n\n\n')
        handler.write('class Test(unittest.TestCase):' + '\n')
        handler.close()

    @staticmethod
    def write_set_up(filename):
        """
        写测试套件的setUp
        :param filename:
        :return:
        """
        handler = open(filename, 'a', encoding='utf-8')
        handler.write('\n    def setUp(self):' + '\n')
        handler.write('        pass\n')
        handler.close()

    @staticmethod
    def write_tear_down(filename):
        """
        写测试套件的tearDown
        :param filename:
        :return:
        """
        handler = open(filename, 'a', encoding='utf-8')
        handler.write('\n    def tearDown(self):' + '\n')
        handler.write('        pass\n')
        handler.close()

    @staticmethod
    def write_case(filename, case):
        """
        根据Excel数据写入用例
        :param filename:
        :param case:
        :return:
        """
        handler = open(filename, 'a', encoding='utf-8')
        if case['case_name'] is None:
            pass
        else:
            handler.write('\n    def ' + case['case_name'] + '(self):\n')
            handler.write("        func_name = inspect.stack()[0][3]\n")
            handler.write("        case = OperationExcel().get_case_by_case_name(func_name)\n")
            handler.write("        resp = ExecCase.exec_case(case)\n")
            handler.write("        expect = case['expect_res']\n")
            handler.write("        print('期望结果', case['expect_res'])\n")
            handler.write("        print('实际结果', resp)\n")
            handler.write("        for k, v in expect.items():\n")
            handler.write("            self.assertEqual(v, OperationJson().search_key(resp, k),"
                          "msg=k + ' is success')\n")
            handler.close()

    def __write_cases(self):
        """
        写入所有测试用例
        :return:
        """
        case_len = len(self.cases)
        for i in range(0, case_len):
            filename = self.cases[i]['module_name']
            filepath = _DEFAULT_CASE_PATH + filename + '.py'
            if not os.path.exists(filepath):
                self.write_head(filepath)
                self.write_set_up(filepath)
                self.write_tear_down(filepath)
            self.write_case(filepath, self.cases[i])

    @staticmethod
    def __set_test_suite():
        """
        设置测试套件
        :return:
        """
        suite = unittest.TestSuite()
        suite_module = []
        modules = OperationExcel().get_module_name_list()
        for module in modules:
            discover = unittest.defaultTestLoader.discover(_DEFAULT_CASE_PATH, pattern=module + '.py')
            suite_module.append(discover)
        for suites in suite_module:
            for test in suites:
                suite.addTest(test)
        return suite

    @staticmethod
    def get_files():
        """
        以列表形式返回某个目录下所有文件名称，不包含子目录
        :return:
        """
        res = []
        for root, dirs, files in os.walk(_DEFAULT_CASE_PATH):
            for file in files:
                if os.path.splitext(file)[1] == ".py":
                    res.append(file)
        return res

    @staticmethod
    def __create_paths():
        """
        创建report目录
        :return:
        """
        if not os.path.exists(_REPORT_PATH):
            os.mkdir(_REPORT_PATH)
        if not os.path.exists(_TEMP_PATH):
            os.mkdir(_TEMP_PATH)

    @staticmethod
    def __init_cases():
        """
        初始化用例，删除已存在用例
        :return:
        """
        modules = OperationExcel().get_module_name_list()
        for module in modules:
            filepath = _DEFAULT_CASE_PATH + module + '.py'
            if os.path.exists(filepath):
                os.remove(filepath)

    def run(self):
        """
        执行所有用例
        :return:
        """
        self.__create_paths()
        self.__init_cases()
        self.__write_cases()
        suite = self.__set_test_suite()
        file = _REPORT_PATH + _NOW + '.html'
        report = open(file, mode='wb')
        title = ReadConfig.FILENAME.split('.')[0]
        runner = HTMLTestRunnerCN.HTMLTestReportCN(stream=report, title=title)
        runner.run(suite)
